• Wednesday, October 2, 2024

    Ryan Carniato's article, "Web Components Are Not the Future," presents a critical perspective on the role of Web Components in web development. Carniato reflects on his previous writings, where he cautiously acknowledged the potential of Web Components but expressed concerns about their practicality. Over time, he has come to believe that Web Components may pose significant risks to the future of web development. The article begins by outlining the vision behind Web Components, which aims to create a standardized way to build reusable components that can be integrated seamlessly into any web application, regardless of the underlying framework. This vision is appealing as it promises a more portable and interoperable web, potentially reducing the need for future migrations. However, Carniato argues that this ideal is fraught with challenges. One of the main issues he highlights is the proliferation of competing standards and frameworks in the JavaScript ecosystem. The existence of numerous frameworks indicates a lack of consensus on how to build components, which undermines the very goal of Web Components to provide a unified approach. Carniato points out that while higher-level abstractions can simplify certain tasks, they can also stifle innovation by creating rigid structures that discourage exploration of alternative solutions. Carniato emphasizes the concept of opportunity cost in framework development, noting that design decisions made early on can have long-lasting implications. He illustrates this with the example of React's development, where the introduction of new features often requires significant time and effort to ensure compatibility with existing components. This complexity can hinder progress and lead to a situation where developers feel constrained by the frameworks they use. The article also critiques the fundamental design of Web Components, particularly the reliance on Custom Elements. Carniato argues that while elements can be components, not all components can be reduced to elements. This distinction complicates the interaction between components and the DOM, leading to inconsistencies and unexpected behaviors. He discusses the challenges posed by the Shadow DOM, which can create barriers to styling and event handling, further complicating the developer experience. Carniato raises concerns about the performance overhead associated with Web Components, particularly in server-side rendering (SSR) scenarios. He argues that while SSR is technically feasible with Web Components, it introduces additional complexity and performance costs that may not be justified. The article suggests that as web development evolves, the focus should shift away from rigid component structures towards more flexible and efficient solutions. In conclusion, Carniato acknowledges that while Web Components may offer ergonomic benefits in specific scenarios, the broader implications of their adoption could hinder innovation and complicate the development landscape. He advocates for a more cautious approach to standardization, emphasizing the need for flexibility and adaptability in web development practices. Ultimately, he posits that the promise of Web Components as a universal solution may be more of a mirage than a reality, urging developers to consider the long-term consequences of their choices in the evolving web ecosystem.

  • Monday, September 30, 2024

    Web components have become a topic of heated debate within the web development community, often sparking discussions about their future and relevance. Recently, Ryan Carniato's assertion that "Web Components Are Not the Future" was met with a counterpoint from Cory LaViska, who argued that they are indeed "the Present." Nolan Lawson, the author of the blog post, aims to bridge this divide and foster a more constructive dialogue. Lawson acknowledges Carniato's contributions to the web framework ecosystem, particularly in performance and framework design. He appreciates the insights shared in Carniato's post but believes there are some misconceptions regarding web components. He emphasizes that while performance is a critical aspect of web development, it is not the sole consideration. Other factors such as maintainability, security, usability, and accessibility also play significant roles in software development. Lawson argues that sometimes trade-offs must be made, and prioritizing performance at the expense of accessibility, for example, is not a viable approach. He draws a parallel between web performance optimization and speedrunning in video games, suggesting that while some developers may focus on micro-optimizations, the broader context of user experience and functionality should not be overlooked. Lawson believes that while minimizing DOM nodes can enhance performance, it is not always necessary to pursue the absolute fastest option. He also points out that custom elements can coexist with different frameworks, allowing for gradual migrations and the composition of micro-frontends. Addressing the concern about the "cost of standards," Lawson argues that supporting web components does not require excessive effort from framework authors. He believes that adapting to new web standards is part of the job and that developers can still create effective frameworks without being hindered by the introduction of new technologies. He acknowledges that some in the web development community may not be interested in web components, but he sees this diversity as a strength rather than a limitation. In conclusion, Lawson agrees with Carniato that web components have their limitations, particularly in areas like server-side rendering and accessibility. However, he also sees value in their use and encourages developers to explore the possibilities they offer. He emphasizes that the web is a vast landscape filled with diverse projects and approaches, and every new capability can serve as an opportunity for creativity. Ultimately, whether or not web components are the right choice depends on the specific needs and constraints of the project at hand.

  • Thursday, September 26, 2024

    The blog post discusses the concept of component composition in React, emphasizing its significance as a core advantage of the framework. Initially, the author reflects on their early experiences with React, highlighting features like the Virtual DOM, one-way data flow, and JSX. However, they argue that the true strength of React lies in its ability to compose components into more complex structures, a practice that was not widely accepted in software development a decade ago. The author addresses the traditional notion of separation of concerns, suggesting that while it still exists, it has evolved. Instead of separating styles, logic, and markup into distinct layers, React encourages grouping them together within components, leading to better code cohesion. This shift allows developers to think in terms of components, which can enhance the organization and maintainability of code. The discussion then shifts to conditional rendering, a common practice in React where components are rendered based on certain conditions. The author presents an example of a `ShoppingList` component that conditionally renders user information and items based on the presence of data. While this approach is acceptable for simple cases, the author warns that it can become problematic when managing multiple states within a single component. As the complexity of the component increases, the author illustrates how conditional rendering can lead to a convoluted structure that is difficult to read and maintain. They propose breaking down the component into smaller, more manageable pieces, suggesting the use of a layout component to encapsulate shared elements while allowing for dynamic content based on the component's state. The author advocates for using early returns to handle different states of a component more clearly. By returning early for each state (e.g., loading, no data, or displaying data), the code becomes easier to follow and reduces cognitive load. This method also facilitates the addition of new conditions, such as error handling, without complicating the existing logic. The post concludes by emphasizing the importance of component composition and the need to avoid excessive conditional rendering. The author encourages developers to embrace early returns and to continually reassess their component structures to ensure clarity and maintainability. They invite readers to engage with them for further discussion or questions, reinforcing the community aspect of learning and sharing knowledge in the React ecosystem.

  • Friday, June 28, 2024

    Front-end development has become unnecessarily complex due to poor choices, such as over-reliance on JavaScript frameworks and ignoring fundamental principles like content importance and CSS capabilities. This complexity leads to frustration and inefficiency. Developers should prioritize simplicity.

  • Friday, May 24, 2024

    This author initially designed a strict, composable design system inspired by Chakra UI to solve inconsistencies and a poorly structured existing design system. However, the system proved difficult for many developers to use due to their lack of experience with functional composition. In hindsight, the author believes a design system built around Tailwind/NativeWind would have been more approachable for developers.

  • Friday, March 29, 2024

    You can drop Web Awesome components anywhere on the web and they'll work - no JavaScript framework is necessary.

  • Thursday, July 11, 2024

    Web developers have a hard time keeping up with new developments that are happening all the time. They also feel like they don't have enough time and/or are getting bored of their jobs.

  • Tuesday, April 16, 2024

    React Server Components (RSCs) allow server-exclusive code, which can lead to better performance. However, this means that popular styling options, like CSS-in-JS libraries which rely on React's lifecycle, can conflict with RSCs. RSC's server-side focus clashes with the browser-centric nature of traditional CSS-in-JS libraries, but there are “zero-runtime” CSS-in-JS libraries that are fully compatible with RSCs today. If your application doesn't use these and already has a good “time-to-interactive” time, then migrating to these libraries is not worth it.

  • Wednesday, June 26, 2024

    Google has stopped active development of Material Web Components, shifting focus to its internal Wiz framework.

  • Tuesday, May 28, 2024

    This article presents a way to implement React-like component-based frontend development in Go using the standard library. Its approach defines components using the define function, composes them using templates, and manages state using URL query parameters.

  • Friday, October 4, 2024

    Since its introduction in 2013, React has evolved significantly, leading to the emergence of various component types. This evolution has resulted in some components becoming essential for modern applications, while others have fallen out of favor or been deprecated. This guide aims to provide beginners with a comprehensive understanding of the different types of React components, highlighting both legacy and modern patterns. Initially, React relied on the `createClass` method for defining components, which allowed developers to create class components without using JavaScript classes. This method was prevalent before the introduction of ES6 in 2015, which brought native class syntax to JavaScript. The `createClass` method enabled developers to define component state and lifecycle methods, although it has since been deprecated and is no longer part of the React core package. Another early pattern was React Mixins, which allowed for the extraction of reusable logic from components. Mixins could encapsulate functionality and be included in components, but they have also been deprecated due to their drawbacks, such as potential naming conflicts and difficulties in tracking the source of methods. With the release of React 0.13, Class Components became the standard for defining components, utilizing ES6 class syntax. Class Components introduced lifecycle methods and allowed for more structured component logic. However, with the introduction of React Hooks in version 16.8, Function Components gained the ability to manage state and side effects, making them the preferred choice for modern React development. Higher-Order Components (HOCs) were another advanced pattern that allowed for the reuse of component logic by wrapping components with additional functionality. However, like Mixins and Class Components, HOCs have seen a decline in usage as developers increasingly favor Function Components with Hooks for sharing logic. Function Components, which were once limited to stateless behavior, have transformed with the introduction of Hooks. They now allow developers to manage state and side effects, making them the industry standard. Custom Hooks can also be created to encapsulate and share logic across components, providing a more modular approach compared to previous patterns. The latest addition to React is Server Components, which enable components to be executed on the server. This approach allows for the delivery of only HTML to the client, optimizing performance and enabling access to server-side resources. Server Components differ from traditional Client Components, which run in the browser and can utilize JavaScript and React Hooks. Async Components are currently supported for Server Components, allowing for asynchronous operations like data fetching before rendering. This capability is expected to extend to Client Components in the future, further enhancing the flexibility of React. Overall, this guide has explored the various types of React components, their historical context, and their relevance in modern development. Understanding these components is crucial for developers looking to build efficient and maintainable React applications.

  • Wednesday, June 19, 2024

    WebContainers allows developers to build instant, interactive coding experiences on the browser. Its team recently released a way to execute, interpret, and refactor AI-generated code directly in the browser. WebContainers provides a secure, sandboxed environment with zero latency, zero compute costs, and zero virtual machines.

  • Tuesday, May 14, 2024

    This author is part of a team that built microservices the “wrong way” where everything depends on everything else and thus it's too difficult to make architectural changes. Commenters give their recommendations, such as collapsing the system to an actual monolith if possible and turning remote calls to local calls.

    Hi Impact
  • Wednesday, July 3, 2024

    React Server Components (RSC) are primarily server-side components that optimize performance by fetching data and rendering on the server, while Client Components handle interactivity and state management on the client side. In the RSC paradigm, Server Components are the default, and Client Components are explicitly marked using 'use client'. While Server Components cannot be directly nested within Client Components, they can be passed as props to Client Components.

  • Monday, April 22, 2024

    One of the root problems with web styling is the “two-tree problem,” which is the need to maintain separate, interconnected trees for document structure (HTML) and styles (CSS). TailwindCSS solves the two-tree problem with atomic CSS, but its composability is limited due to potential CSS class conflicts. Styled components offer composability, but don't solve the two-tree problem. Inline styles combined with JavaScript can handle most styling needs without running into the two-tree problem.

  • Monday, May 27, 2024

    This author dislikes the current state of the internet due to paywalls on useful articles, outdated StackOverflow answers, automatic pop-ups for login and modals, and cookie consent banners. The constant need to close popups and banners on websites is annoying.

  • Tuesday, March 12, 2024

    There is a widespread disregard for front-end development within the tech industry. Frontend work is sometimes biased against as there are beliefs that frontend is less technical and thus, less valued. This devaluing of frontend work harms the quality of software products and limits the potential of the web.

  • Friday, April 26, 2024

    Jim Nielsen discusses the limitations of the "LEGO" analogy for design systems, arguing that prefabricated components have less value in the age of generative AI and open-source libraries. Even with prefabricated components, custom "one-off" designs are still necessary for each product, and a successful design system needs more than just prefabrication and composition.

  • Friday, September 27, 2024

    The article discusses the importance of design systems from a developer's perspective, emphasizing how they can enhance usability and streamline the development process. It begins with an analogy comparing the intuitive experience of riding a bicycle to the desired user experience in software applications. Just as riding a bike becomes second nature, the goal is to create software that users can navigate effortlessly. Design systems are presented as a solution to achieve this level of usability, allowing teams to build and ship applications quickly while maintaining consistency through standardized components. The piece highlights the potential pitfalls of poorly implemented design systems, which can hinder rather than help development. It stresses the need to treat design systems as products that require ongoing investment and maintenance to remain effective. A well-maintained design system can provide stability and speed up development, while a neglected one can lead to technical debt and inefficiencies. The article advocates for an iterative approach to building design systems, contrasting it with the traditional waterfall method. Developers are encouraged to focus on simplicity and to build design systems incrementally, using user feedback to guide improvements. The example of Slack illustrates this point, showing how the company managed to standardize its components without sacrificing development speed, ultimately leading to the creation of Slack Kit. Another critical aspect discussed is the necessity of maintaining design systems to prevent them from becoming obsolete. Developers often express skepticism about using design systems due to past experiences with poorly maintained products. The article suggests that design systems should be flexible and adaptable, allowing for both standardization and customization. The Spotify design system, Encore, is cited as an example of balancing consistency with the need for creative freedom. The importance of alignment between developers and designers is also emphasized. Effective communication and collaboration can prevent wasted effort and ensure that both teams are working towards the same goals. The article uses Airbnb's experience to illustrate how a shared visual language can enhance productivity and consistency across teams. Finally, the article encourages viewing design systems as basecamps for exploration rather than constraints on creativity. By providing a stable foundation, design systems can empower developers and designers to innovate and experiment without losing sight of consistency and usability. The piece concludes by promoting UXPin Merge as a tool that facilitates the creation of production-ready prototypes, further enhancing the design and development workflow.

  • Friday, October 4, 2024

    Sahil Lavingia, the CEO of Gumroad, shared insights on the decision-making process regarding the technology stack for a new project called Helper. Initially, there was optimism about using htmx, a framework designed to simplify interactions in web applications. Lavingia's enthusiasm was influenced by past experiences with React, which he felt was often too complex for their needs. He believed htmx could provide a lightweight alternative for adding simple interactions. However, as the project progressed, the team encountered several challenges that led them to abandon htmx in favor of React and Next.js. One of the primary issues was the developer experience; while htmx could technically accomplish their goals, the process felt forced and less intuitive compared to the natural flow they experienced with Next.js. This was particularly evident when building complex forms that required dynamic validation and conditional fields, where htmx necessitated convoluted server-side logic. User experience also suffered with htmx, as it tended to push the application towards a Rails/CRUD approach, resulting in a generic and uninspiring interface. The team faced significant hurdles when trying to implement features like drag-and-drop functionality, which was much smoother and more efficient with React libraries. Another factor was the support from AI tools, which were more familiar with Next.js than htmx. This discrepancy affected their development speed and problem-solving capabilities, as resources for React/Next.js were more abundant and accessible. As the project grew in complexity, htmx's limitations became more pronounced. The simplicity that initially attracted the team began to feel restrictive, especially when they needed to implement sophisticated interactions and manage state across multiple components. The vast ecosystem surrounding React and Next.js provided solutions to many challenges, whereas htmx often required the team to create custom solutions or compromise on functionality. Ultimately, the transition to React and Next.js allowed Gumroad to enhance the user experience significantly. Features like drag-and-drop functionality, complex state management, dynamic form generation, and real-time collaboration were easier to implement and optimize within the React ecosystem. The team found that React's tools and libraries facilitated a more engaging and responsive application. Lavingia concluded that while htmx has its merits, particularly for simpler projects or those built on existing server-rendered applications, the specific needs of the Helper project made React and Next.js the better choice. He acknowledged the importance of selecting technologies that can grow with a project and support long-term goals. The experience reinforced the idea that understanding a project's unique requirements is crucial in choosing the right tools, and he remains open to reevaluating their tech stack as needs evolve and new technologies emerge.

  • Monday, April 29, 2024

    Web development started with simple HTML and CSS. Eventually, client-side JavaScript allowed for more dynamic websites. The need for SEO and performance led to the creation of server-side rendering and frameworks like Next.js. JavaScript's shortcomings led to TypeScript and Svelte. At the end of the day, the core goal of all these evolutions was to create enjoyable user experiences, so the tools being used don't matter much.

  • Friday, August 2, 2024

    React introduced the concept of a "virtual DOM" to optimize web app rendering. Its popularity led to widespread adoption, but also to criticisms regarding its learning curve, state management, and performance. While React's defenders highlight its improvements in recent versions, alternative frameworks like Svelte and Astro offer simpler approaches without relying on the virtual DOM.

  • Wednesday, March 6, 2024

    React 19 introduces several significant improvements designed to streamline development and boost application performance. Key features include a performance-enhancing compiler, simplified form handling with Actions, server-side rendering optimizations with Server Components, and better integration with Web Components. The update promises faster rendering, smoother user experiences, and easier development workflows.

    Hi Impact
  • Friday, September 27, 2024

    The author reflects on their experience with the Rust programming language, likening it to the first generation of the iPhone—innovative but incomplete. Initially captivated by Rust's features such as memory safety and a modern package manager, the author expresses frustration after four years of use, feeling that the language has stagnated. They note a significant slowdown in the introduction of new features, with many promising ideas, like coroutines, remaining unimplemented despite being in the pipeline for years. The author suggests that the Rust community's consensus process has become unwieldy, leading to a graveyard of good ideas that never see the light of day. The author fantasizes about forking the Rust compiler to create a new version of the language, which they refer to as "seph." They propose several changes, starting with the introduction of function traits, which would allow developers to specify properties of functions, such as whether they can panic or if they are pure. This would enhance the language's ability to guarantee certain behaviors at compile time, addressing concerns like ensuring that specific blocks of code do not panic. Another significant proposal involves implementing compile-time capabilities to mitigate supply chain risks associated with third-party crates. The author suggests that functions interacting with sensitive operations, like file system access, should be marked with capabilities that require explicit whitelisting in a project's configuration. This would prevent potentially malicious code from being executed without the developer's knowledge. The author also critiques the complexity of Rust's Pin and borrow checker, arguing that the current implementation complicates the language unnecessarily. They propose a more intuitive system that would allow developers to express borrowing semantics directly in their code, making it easier to work with self-referential structures and async functions. Additionally, the author expresses admiration for Zig's compile-time capabilities, suggesting that Rust could benefit from a similar approach that allows developers to write compile-time code using the same syntax as regular Rust. They also list smaller improvements they would like to see, such as better ergonomics for raw pointers and enhancements to the language's collection types. In closing, the author acknowledges that many of their proposed changes would be incompatible with existing Rust, potentially requiring a new edition of the language. They express reluctance to engage with the RFC process, feeling that it often leads to frustration and unfulfilled ideas. Ultimately, they contemplate the possibility of forking Rust to implement their vision, though they recognize the challenges involved in such an endeavor.

  • Tuesday, October 1, 2024

    In today's technology landscape, there is an overwhelming abundance of frameworks, libraries, and plugins that promise to streamline development and reduce costs. Many businesses eagerly adopt these external codebases, hoping to accelerate their time to market. However, a significant number of developers overlook the hidden costs and risks associated with relying on these external solutions. One of the most critical considerations is security. Regardless of whether the code was written in-house or sourced externally, the responsibility for every line of code in a project ultimately falls on the organization. The consequences of a security breach are severe, whether the vulnerability lies in an external library or internal code. While external codebases may seem appealing, they often introduce a larger attack surface, making it easier for malicious actors to exploit vulnerabilities. In contrast, internally developed code tends to be more focused and task-specific, which can significantly reduce security risks. Dependency on external codebases can create substantial risks throughout a project's lifecycle. Many libraries have their own dependencies, leading to complex dependency graphs that can complicate maintenance and increase vulnerability exposure. Even after thorough research to select an appropriate library, the landscape can change rapidly. A library that seemed suitable six months ago may no longer be actively maintained or may undergo significant changes that require ongoing integration work. This can lead to a cycle of dependency management that consumes valuable resources. Moreover, the notion that free libraries come without cost is misleading. Organizations must account for the time and effort spent on researching, evaluating, integrating, and maintaining these external codebases. When comparing the total cost of using an external library to developing a targeted internal solution, it often becomes evident that the latter is more cost-effective in the long run. In building BotBarrier, the team prioritized minimizing dependencies to only those essential functions that could not be developed in-house. This approach allows for greater control over the product and reduces the burden of managing unnecessary dependencies. By opting to create their own backend and frontend frameworks, the team limited their reliance on external libraries, using only three essential SDKs for specific functionalities. Ultimately, the goal is to maintain the flexibility to adapt and innovate without being tethered to the latest trends in technology. Organizations should strive to make informed decisions about their dependencies, focusing on what they can control and ensuring that their development efforts align with their business objectives. By doing so, they can safeguard their projects against the risks associated with external codebases while fostering a more secure and efficient development environment.